﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Hive.Core
{
    public static class Extensions
    {
        public static void Iter<T>(this T[,] map, Action<int, int, T> a)
        {
            for (int row = 0; row < map.Height(); row++)
                for (int col = 0; col < map.Width(); col++)
                    a(row, col, map[row, col]);
        }
        
        public static int Height<T>(this T[,] map)
        {
            return map.GetLength(0);
        }

        public static int Width<T>(this T[,] map)
        {
            return map.GetLength(1);
        }

        public static T[,] RemoveRow<T>(this T[,] map, int index)
        {
            var result = new T[map.Height() - 1, map.Width()];
            var rowSkipped = 0;

            for (var t = 0; t < map.Height(); t++)
            {
                if (t != index)
                {
                    for (var a = 0; a < map.Width(); a++)
                    {
                        result[t - rowSkipped, a] = map[t, a];
                    }
                }
                else
                {
                    rowSkipped = 1;
                }
            }

            return result;
        }

        public static T At<T>(this T[,] map, Location l)
        {
            return map[l.Row, l.Col];
        }

        // Fisher-Yates shuffle courtesy of StackOverflow
        public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
        {
            T[] elements = source.ToArray();
            // Note i > 0 to avoid final pointless iteration
            for (int i = elements.Length - 1; i > 0; i--)
            {
                // Swap element "i" with a random earlier element it (or itself)
                int swapIndex = rng.Next(i + 1);
                T tmp = elements[i];
                elements[i] = elements[swapIndex];
                elements[swapIndex] = tmp;
            }
            // Lazily yield (avoiding aliasing issues etc)
            foreach (T element in elements)
            {
                yield return element;
            }
        }

        public static IEnumerable<T> Merge<T>(this IEnumerable<T> left, IEnumerable<T> right)
        {
            return left.Intersect(right).Union(right.Except(left));
        }
    }

    public static class LocationExtensions
    {
        public static Location Normalize(this Location l)
        {
            int row = l.Row % Env.Map.Height;
            if (row < 0) row += Env.Map.Height; // because the modulo of a negative number is negative

            int col = l.Col % Env.Map.Width;
            if (col < 0) col += Env.Map.Width;

            return new Location(row, col);
        }
    }
}
